package cn.tqfeiyang.springplus.framework.toolkit;

import cn.tqfeiyang.springplus.framework.Constants;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletRequestWrapper;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public final class RequestUtils {


    /**
     * 是否是本地请求？
     *
     * @param request
     * @return
     */
    public static boolean isLocalhostMode(HttpServletRequest request) {
        if ("localhost".equalsIgnoreCase(request.getServerName())
                || "127.0.0.1".equalsIgnoreCase(request.getServerName())) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 是否是本地请求？
     *
     * @param request
     * @return
     */
    public static boolean isDebugRequest(HttpServletRequest request) {
        return BooleanUtils.toBoolean(request.getHeader(Constants.DEBUG_REQUEST_HEADER));
    }


    /**
     * 获取请求数据，用于发生错误时输出给调用者，方便问题排查。
     *
     * @param request
     * @return 请求数据
     */
    public static Map<String, Object> getRequestData(HttpServletRequest request) {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("requestURI", request.getRequestURI());
        //dataMap.put("clientIp", NetworkUtils.getRequestIp(request));
        dataMap.put("queryString", request.getQueryString());
        dataMap.put("method", request.getMethod());
        //dataMap.put("parameters", getParametersJson(request));
        //dataMap.put("headers", getHeadersJson(request));
        dataMap.put("characterEncoding", request.getCharacterEncoding());
        dataMap.put("contentType", request.getContentType());

//        ContentCachingRequestWrapper contentCachingRequestWrapper = getContentCachingRequestWrapper(request);
//        if (contentCachingRequestWrapper != null) {
//            dataMap.put("requestBody",  new String(contentCachingRequestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8));
//        }

        return dataMap;
    }

    private static ContentCachingRequestWrapper getContentCachingRequestWrapper(HttpServletRequest request) {
        ContentCachingRequestWrapper cachingRequestWrapper = null;

        ServletRequestWrapper servletRequestWrapper = null;
        if (request instanceof ServletRequestWrapper) {
            servletRequestWrapper = (ServletRequestWrapper) request;
        }

        while (servletRequestWrapper != null) {
            if (servletRequestWrapper instanceof ContentCachingRequestWrapper) {
                cachingRequestWrapper = (ContentCachingRequestWrapper) servletRequestWrapper;
                break;
            }

            ServletRequest superRequest = servletRequestWrapper.getRequest();
            if (superRequest != null && superRequest instanceof ServletRequestWrapper) {
                servletRequestWrapper = (ServletRequestWrapper) superRequest;
            } else {
                servletRequestWrapper = null;
            }
        }

        return cachingRequestWrapper;
    }

    /**
     * 获取请求头数据
     *
     * @param request
     * @return JSON
     */
    public static String getHeadersJson(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement();
            map.put(name, request.getHeader(name));
        }
        return map.size() > 0 ? JsonUtils.toJsonString(map) : null;
    }

    /**
     * 获取请求参数数据
     *
     * 如果参数有多个值，则返回数组；如果参数只有一个值，则返回字符串。
     *
     * @param request
     * @return JSON
     */
    public static String getParametersJson(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        request.getParameterMap().forEach((k, v) -> map.put(k, v.length > 1 ? v : v[0]));
        return map.size() > 0 ? JsonUtils.toJsonString(map) : null;
    }

}